package database.model;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import database.HibernateUtil;
@Entity
@Table(name = "SECTION")
public class Section implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = -4453721837099051370L;
	private Long _id;
	private String _url;
	private String _title;
	private String _description;
	private String _pubDate;
	private Date _lastBuildDate;
	private List<Article> _articles;
	
	
	public static Section update (String rssUrl,InputStream inputStream)
	{
		Session session = HibernateUtil.currentSession();
		Transaction trans = session.beginTransaction();
		
		Section section  = Section._getSectionWithUrl(session,rssUrl);
		boolean isUpdate = section != null;
		if(!isUpdate) section = new Section();
		section.setUrl(rssUrl);
		Document document;
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			document = factory.newDocumentBuilder().parse(inputStream);
			document.getDocumentElement().normalize();
			Element channelElement = (Element) document.getElementsByTagName("channel").item(0);
			section.setTitle(channelElement.getElementsByTagName("title").item(0).getTextContent()
					.replaceAll(" - VnExpress.net", ""));
			section.setDescription(channelElement.getElementsByTagName("description").item(0).getTextContent());
			//_url = channelElement.getElementsByTagName("link").item(0).getTextContent();
			section.setPubDate(channelElement.getElementsByTagName("pubDate").item(0).getTextContent());
			List<Article> articles = section.getArticles();
			
			if(articles == null)
			{
				articles = new ArrayList<Article>();
			}
			Map<String,Article> articlesUrls = new HashMap<String,Article>();
			for(Article anArticle:articles)
			{
				articlesUrls.put(anArticle.getUrl(), anArticle);
			}
			NodeList nodeList = channelElement.getElementsByTagName("item");
			for(int i= 0;i< nodeList.getLength();i++)
			{
				String articleUrl = ((Element)nodeList.item(i)).getElementsByTagName("link").item(0).getTextContent();
				Article article = null;
				if(articlesUrls.containsKey(articleUrl))
				{ 
					article = articlesUrls.get(articleUrl);
					articlesUrls.remove(article);
				}
				else
				{
					article = Article.getArticleWithUrl(session, articleUrl);
					boolean isUpdateArticle = article != null;
					if(!isUpdateArticle)
					{
						article = new Article();
						article.setUrl(articleUrl);
						
					}
					
					article.save(session,isUpdateArticle);
					articles.add(article);
				}
			}
			
			/*for(Article anArticle: articlesUrls.values())
			{
				articles.remove(anArticle);
			}*/
			
			section.setArticles(articles);

			section.setLastBuildDate(new Date());
			section._save(session,isUpdate);
			
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		finally
		{
			trans.commit();
			HibernateUtil.closeSession();
		}
		
		return section;
	}
	
	/*public static Section getSectionWithUrl(String url)
	{
		Session session = HibernateUtil.currentSession();
		Transaction trans = session.beginTransaction();
		Section section = Section._getSectionWithUrl(session, url);
		trans.commit();
		HibernateUtil.closeSession();
		return section;
	}*/
	private static Section _getSectionWithUrl(Session session,String url)
	{
		@SuppressWarnings("unchecked")
		List<Section> list =  session.createCriteria(Section.class).setFetchSize(1).add(Restrictions.like("url", url)).list();
		return list.size() == 0? null:list.get(0);
	}
	
	public static Section getSectionById(Session session,Long id)
	{
		@SuppressWarnings("unchecked")
		List<Section> list =  session.createCriteria(Section.class).setFetchSize(1).add(Restrictions.like("SECTION_ID", id)).list();
		return list.size() == 0? null:list.get(0);
	}
	
	
	/*public void save(boolean isUpdate)
	{
		Session session = HibernateUtil.currentSession();
		Transaction trans = session.beginTransaction();
		_save(session, isUpdate);
		trans.commit();
		HibernateUtil.closeSession();
	}*/
	private void _save(Session session,boolean isUpdate)
	{
		if(isUpdate)
			session.update(this);
		else
			session.save(this);
	}
	
	//--------------------------------------------------------------------------------------------------------
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column(name = "SECTION_ID")
	public Long getId(){ return _id; }
	public void setId(Long id){ _id = id; } 
	
	public String getUrl(){ return _url; }
	public void setUrl(String url){ _url = url;}
	
	public String getPubDate(){ return _pubDate; }
	public void setPubDate(String pubDate){ _pubDate = pubDate; }
	
	public Date getLastBuildDate(){ return _lastBuildDate; }
	public void setLastBuildDate(Date lastBuildDate){ _lastBuildDate = lastBuildDate; }
	
	@Column(columnDefinition="MEDIUMTEXT")
	public String getTitle(){ return _title; }
	public void setTitle(String title) { _title = title; }

	@Column(columnDefinition="LONGTEXT")
	public String getDescription(){ return _description; }
	public void setDescription(String description){ _description = description; }
	
	@ManyToMany(
	        targetEntity=database.model.Article.class,
	        cascade={CascadeType.PERSIST, CascadeType.MERGE}
	    )
	    @JoinTable(
	        name="SECTION_ARTICLE",
	        joinColumns=@JoinColumn(name="SECTION_ID"),
	        inverseJoinColumns=@JoinColumn(name="ARTICLE_ID")
	    )
	public List<Article> getArticles()
	{ 
		return _articles; 
	}
	public void setArticles(List<Article> articles){ _articles = articles; }
}
